package org.osomit.sacct.security.otp.impl;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

import org.apache.commons.codec.binary.Base64;
import org.osomit.sacct.security.otp.iface.OTPProfileRegistryLoader;
import org.osomit.sacct.security.otp.iface.OTPProfileRegistry;
import org.osomit.sacct.security.utils.SymmetricCipher;
import org.osomit.sacct.security.utils.Serializer;


/**
 * Load and Persist the OTP Profile Registry to and from the file system
 *
 * @author Jian Fang (John.Jian.Fang@gmail.com)
 *
 * Date: Jun 26, 2009
 */
public class FileOTPProfileRegistryLoader implements OTPProfileRegistryLoader {
	static int TYPICAL_SIZE = 1024;

	private String fileName;

	//DES password to protect the file
	private String password;

	/**ApplicationOTPProfile
	 * @return the fileName
	 */
	public final String getFileName() {
		return fileName;
	}

	/**
	 * @param fileName the fileName to set
	 */
	public final void setFileName(String fileName) {
		this.fileName = fileName;
	}

	/**
	 * @return the password
	 */
	public final String getPassword() {
		return password;
	}

	/**
	 * @param password the password to set
	 */
	public final void setPassword(String password) {
		this.password = password;
	}

	public void load(OTPProfileRegistry registry) throws Exception{
		if(this.fileName == null || this.password == null)
			return;

		FileInputStream fin = new FileInputStream (this.fileName);
		BufferedReader br = new BufferedReader(new InputStreamReader(fin));
		StringBuffer sb = new StringBuffer(TYPICAL_SIZE);
		String line = null;
		while((line = br.readLine()) != null){
			sb.append(line);
		}

		fin.close();
		br.close();

		if(sb.length() > 0){
			byte[] encrypted = Base64.decodeBase64(sb.toString().getBytes());
			byte[] decrypted = SymmetricCipher.desDecrypt(this.password, encrypted);
			ArrayList<OTPProfile> profiles = Serializer.decompressAndDeserialize(decrypted, false);

			if(profiles != null && profiles.size() > 0){
				Iterator it = profiles.iterator();
				while(it.hasNext()){
					OTPProfile profile = (OTPProfile)it.next();
					registry.addOTPProfile(profile);
				}
			}
		}
	}

	public void persist(OTPProfileRegistry registry) throws Exception {
		if(this.fileName == null || registry == null || this.password == null)
			return;

		Collection<OTPProfile> collection = registry.getOTPProfiles();
		ArrayList<OTPProfile> list = new ArrayList<OTPProfile>();
		list.addAll(collection);
		byte[] serialized = Serializer.serializeAndCompress(list, false);
		byte[] encrypted = SymmetricCipher.desEncrypt(password, serialized);
		String result = new String(Base64.encodeBase64(encrypted), "UTF8");

		FileOutputStream fout = new FileOutputStream(this.fileName, false);
		fout.write(result.getBytes());
		fout.close();
	}
}
